﻿using Naruto.Redis.Interface;
using Naruto.Redis.Config;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Naruto.Redis.Connection;

namespace Naruto.Redis.Internal
{
    /// <summary>
    /// 
    /// </summary>
    public class RedisSet : IRedisSet
    {
        private readonly IRedisConnection redisConnection;

        private readonly RedisPrefixKey redisPrefixKey;

        /// <summary>
        /// 实例化连接
        /// </summary>
        public RedisSet(IRedisConnection _redisConnection, IOptions<RedisOptions> options)
        {
            redisConnection = _redisConnection;
            //初始化key的前缀
            redisPrefixKey = options.Value.RedisPrefix ?? new RedisPrefixKey();
        }
        #region 同步
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Add<T>(string value) => Add<T>(redisConnection.DataBase, value);
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Remove<T>(string value) => Remove<T>(redisConnection.DataBase, value);
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public string[] Get<T>() => Get<T>(redisConnection.DataBase);
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public string[] Get(string key) => Get(redisConnection.DataBase, key);
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Add(string key, string value) => Add(redisConnection.DataBase, key, value);
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Remove(string key, string value) => Remove(redisConnection.DataBase, key, value);
        #endregion
        #region 异步
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> AddAsync<T>(string value) => await AddAsync<T>(redisConnection.DataBase, value);
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> RemoveAsync<T>(string value) => await RemoveAsync<T>(redisConnection.DataBase, value);
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public async Task<string[]> GetAsync<T>() => await GetAsync<T>(redisConnection.DataBase);
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public async Task<string[]> GetAsync(string key) => await GetAsync(redisConnection.DataBase, key);
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> AddAsync(string key, string value) => await AddAsync(redisConnection.DataBase, key, value);
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> RemoveAsync(string key, string value) => await RemoveAsync(redisConnection.DataBase, key, value);
        #endregion

        #region database

        #region 同步
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Add<T>(int dataBase, string value)
        {

            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return redisConnection.Data(dataBase).SetAdd(key, value);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Remove<T>(int dataBase, string value)
        {

            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return redisConnection.Data(dataBase).SetRemove(key, value);
        }
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public string[] Get<T>(int dataBase)
        {
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return redisConnection.Data(dataBase).SetMembers(key).ToStringArray();
        }
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public string[] Get(int dataBase, string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return redisConnection.Data(dataBase).SetMembers(redisPrefixKey.SetPrefixKey + key).ToStringArray();
        }
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Add(int dataBase, string key, string value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            return redisConnection.Data(dataBase).SetAdd(redisPrefixKey.SetPrefixKey + key, value);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Remove(int dataBase, string key, string value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            redisConnection.Data(dataBase).SetRemove(redisPrefixKey.SetPrefixKey + key, value);
        }
        #endregion
        #region 异步
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> AddAsync<T>(int dataBase, string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return await redisConnection.Data(dataBase).SetAddAsync(key, value).ConfigureAwait(false);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> RemoveAsync<T>(int dataBase, string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return await redisConnection.Data(dataBase).SetRemoveAsync(key, value).ConfigureAwait(false);
        }
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public async Task<string[]> GetAsync<T>(int dataBase)
        {
            //反射实体的信息
            var type = typeof(T);
            string key = redisPrefixKey.SetPrefixKey + type.Name;
            return (await redisConnection.Data(dataBase).SetMembersAsync(key).ConfigureAwait(false)).ToStringArray();
        }
        /// <summary>
        /// 取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public async Task<string[]> GetAsync(int dataBase, string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            return (await redisConnection.Data(dataBase).SetMembersAsync(redisPrefixKey.SetPrefixKey + key).ConfigureAwait(false)).ToStringArray();
        }
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> AddAsync(int dataBase, string key, string value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            return await redisConnection.Data(dataBase).SetAddAsync(redisPrefixKey.SetPrefixKey + key, value).ConfigureAwait(false);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<bool> RemoveAsync(int dataBase, string key, string value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(nameof(value));
            }
            return await redisConnection.Data(dataBase).SetRemoveAsync(redisPrefixKey.SetPrefixKey + key, value).ConfigureAwait(false);
        }
        #endregion

        #endregion
    }
}
